package com.baidu.sggc.controller;

import com.baidu.sggc.audit.extend.AuditExtendContext;
import com.baidu.sggc.audit.extend.FileMessage;
import com.baidu.sggc.audit.extend.GeneralMessage;
import com.baidu.sggc.core.annotation.AuditLog;
import com.baidu.sggc.core.common.R;
import com.baidu.sggc.core.service.MinioService;
import com.baidu.sggc.entity.vo.FsVo;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Controller
@RequestMapping("/fs")
public class FsController {

  @Autowired
  private MinioService minioService;

  @Operation(summary = "上传文件", description = "上传文件")
  @PostMapping(value = "/upload", headers = "content-type=multipart/form-data")
  @ResponseBody
  @AuditLog(module = "文件管理", auditObject = "模型文件", operation = "upload", message = "上传模型文件")
  public R<FsVo> uploadFile(@RequestParam("file") MultipartFile file) {
    System.out.println("/fs/upload" + ": " + LocalDateTime.now());

    String fileName = file.getOriginalFilename();
    if (fileName == null || !fileName.toLowerCase().endsWith(".md")) {
      return R.err("只能上传.md格式文件");
    }

    // 审计扩展字段：FileMessage
    FileMessage msg = new FileMessage();
    Map<String, List<String>> fileMap = new HashMap<>();
    fileMap.put("模型目录", Collections.singletonList(fileName));
    msg.setFileInfo(fileMap);
    AuditExtendContext.setExtendData(toMap(msg));

    return R.ok(minioService.uploadObject(file));
  }

  @GetMapping("/download/{object}")
  @ResponseBody
  @AuditLog(module = "文件管理", auditObject = "模型文件", operation = "download", message = "下载模型文件")
  public ResponseEntity<InputStreamResource> downloadFile(@PathVariable String object) {
    System.out.println("/fs/download" + ": " + LocalDateTime.now());
    try {
      // 从 MinIO 获取文件流
      InputStream fileStream = minioService.downloadFile(object);

      // 设置响应头
      String encodedFileName = URLEncoder.encode(object, StandardCharsets.UTF_8.toString());

      HttpHeaders headers = new HttpHeaders();
      headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename*=UTF-8''" + encodedFileName);
      headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
      // 返回文件流
      return ResponseEntity.ok()
              .headers(headers)
              .body(new InputStreamResource(fileStream));
    } catch (Exception e) {
      System.out.println("文件下载失败" + e);
      return ResponseEntity.status(500).body(null);
    }
  }

  @GetMapping("/del/{object}")
  @ResponseBody
  @AuditLog(module = "文件管理", auditObject = "模型文件", operation = "delete", message = "删除模型文件")
  public R<String> del(@PathVariable String object) {
    System.out.println("/fs/del" + ": " + LocalDateTime.now());
    try {
      minioService.deleteFile(object);

      // 审计扩展字段：GeneralMessage
      GeneralMessage msg = new GeneralMessage();
      msg.setDataType("模型文件");
      msg.setDataName(object);
      msg.setUniqueIdentification(Collections.singletonList(object));
      msg.setOperationNum(1);
      AuditExtendContext.setExtendData(toMap(msg));

      return R.ok("文件删除成功");
    } catch (Exception e) {
      System.out.println("文件删除失败" + e);
      return R.err("文件删除失败");
    }
  }

  private Map<String, Object> toMap(Object obj) {
    ObjectMapper mapper = new ObjectMapper();
    return mapper.convertValue(obj, Map.class);
  }
}
